using System.Net;
using System.Net.Mail;
using System.Text;
using Microsoft.Extensions.Logging;
using Vin.Extension.Email.Options;
using Vin.Tool.AspNetCore.Service;
using Vin.Tool.AspNetCore.Singleton;
using Vin.Tool.Core.AssertCategory;
using Vin.Tool.Core.BasicTypeCategory;
using Vin.Tool.Domain.ExceptionModel;

namespace Vin.Extension.Email.Service;

public class VinEmailService : VinBaseService
{
    public VinEmailOption Option => VinApp.GetConfig<VinEmailOption>();

    public async Task SendEmail(List<string> receivers, string title,
        string template, object? templateData, VinEmailSendOption? emailOption = null)
    {
        var content = template.Format(templateData);
        emailOption ??= new VinEmailSendOption();

        if (emailOption.Receivers.Count <= 0 && receivers.Count <= 0)
        {
            throw new BusinessException("至少需要一个收件人");
        }

        receivers = receivers.Where(x => x.IsNotNullOrWhiteSpace()).ToList();
        try
        {
            var mail = new MailMessage
            {
                From = new MailAddress(Option.Sender, emailOption.FromName ?? Option.SenderName,
                    Encoding.UTF8), // 发件人邮箱地址
                Subject = title, // 邮件标题
                Body = content, // 邮件内容
                IsBodyHtml = emailOption.IsHtml, // 是否支持html
                Priority = emailOption.Priority, // 邮件优先级
            };

            if (emailOption.Receivers.Count > 0)
            {
                emailOption.Receivers.ForEach(x =>
                    mail.To.Add(new MailAddress(x.Email, x.Name, Encoding.UTF8))); // 收件人邮箱地址
            }
            else
            {
                receivers.ForEach(x => mail.To.Add(x)); // 收件人邮箱地址
            }

            emailOption.CcList.ForEach(x => mail.CC.Add(x)); // 抄送
            emailOption.Attachments.ForEach(x => mail.Attachments.Add(x)); // 附件

            var client = new SmtpClient();
            if (Option.Host.IsNotNullOrWhiteSpace())
            {
                client.Host = Option.Host!;
            }

            if (Option.Port.HasValue)
            {
                client.Port = Option.Port.Value;
            }

            client.Credentials = new NetworkCredential(Option.Sender, Option.SenderPwd);
            client.EnableSsl = Option.EnableSsl;

            await client.SendMailAsync(mail);
        }
        catch (Exception e)
        {
            Logger.LogTrace(e, "发送邮件失败");
        }
    }
}